#include<cstdio>
#include"dictionary.h"
#include"hasher.h"
#include"logger.h"

#include<string>
#include<map>
#include<exception>
using namespace std;
using namespace Compression;
using namespace Parser;
using namespace Hashing;
using namespace MyVector;
using namespace Stream;
using namespace SearchEngine;
using namespace Custom;





int main(int argc,char **argv)
{
	try
	{
		map<string,string> setup;
		FILE *cfg = fopen("setup.cfg","rb");
		Logger logger(stderr,LogLevel::Debug);
		if (!cfg)
		{
			logger.Log((LogLevel)(LogLevel::Debug|LogLevel::Info),"brak pliku konfiguracyjnego setup.cfg");
			return 0;
		}
		char cmd[30],value[100];
		while (fscanf(cfg,"%s%s",cmd,value)==2)
			setup[cmd]=value;
		fclose(cfg);
		double pageRankScore=0;
		double titleCountScore=0;
		double textCountScore=0;
		double wordDistanceScore=0;
		if (setup.find("PageRankScore")!=setup.end())
			pageRankScore = Double::Parse(setup["PageRankScore"]);
		if (setup.find("TitleCountScore")!=setup.end())
			titleCountScore = Double::Parse(setup["TitleCountScore"]);
		if (setup.find("TextCountScore")!=setup.end())
			textCountScore = Double::Parse(setup["TextCountScore"]);
		if (setup.find("WordDistanceScore")!=setup.end())
			wordDistanceScore = Double::Parse(setup["WordDistanceScore"]);

		if (setup.find("filename")==setup.end())
		{
			logger.Log((LogLevel)(LogLevel::Debug|LogLevel::Info),"nie podano nazwy pliku z wikipedia: filename");
			return 0;
		}
		if (setup.find("basePath")==setup.end())
		{
			logger.Log((LogLevel)(LogLevel::Debug|LogLevel::Info),"nie podano nazwy katalogu z wikipedia: basePath");
			return 0;
		}
		logger.AddLog(setup["basePath"]+"logs\\"+Logger::DefaultLogName(),LogLevel::Info);
		dictionary IRsystem(setup["basePath"],setup["filename"],setup["stemming"]=="true");
		IRsystem.ScoreSystem.PageRank = pageRankScore;
		IRsystem.ScoreSystem.Title = titleCountScore;
		IRsystem.ScoreSystem.Text = textCountScore;
		IRsystem.ScoreSystem.WordDistance = wordDistanceScore;
		if (setup["buildAll"]=="true")
			IRsystem.buildAll(setup["filename"].c_str());
		if (setup["loadIndex"]=="true")
            IRsystem.loadIndex(setup.find("pagerank_ppb")==setup.end() ? "" :SearchEngine::PageRankFileName(Double::Parse(setup["pagerank_ppb"])));
		if (setup["query"] == "true")
		{
			char query[3000];
			if (setup["queryFile"] == "stdin")
			{
				while (1)
				{
					gets(query);
					IRsystem.showPostingList(IRsystem.Query(query),"results\\stdio.txt",query);
				}
			}
			else
			{
				logger.Log((LogLevel)(LogLevel::Debug|LogLevel::Info),"etap zapytan:");
				FastIstream queries(fopen((setup["basePath"]+setup["queryFile"]).c_str(),"r"));
				string resultFile = setup.find("resultFile") == setup.end() ? "results.txt" : setup["resultFile"];
				FILE *file = fopen(("results\\"+resultFile).c_str(),"w");
				fclose(file);
		#ifdef STATS
				FILE *queryStat = fopen((setup["basePath"]+"\\stats\\query_"+setup["queryFile"]).c_str(),"w");
				fprintf(queryStat,"Zapytanie;Czas\n");
				fprintf(queryStat,"0;0\n");
				time_t queryStatTime = time(0);
				int queryNr = 0;
		#endif
				while (queries.getLine(query))
				{
					time_t startTime = time(0);
					//fprintf(stderr,"zapytanie: %s\n",query);
					IRsystem.showPostingList(IRsystem.Query(query),("results\\"+resultFile).c_str(),query);
		#ifdef STATS
					++queryNr;
					if (queryNr % 10 == 0)
					{
						fprintf(queryStat,"%d;%.2lf\n",queryNr,difftime(time(0),queryStatTime));
					}
		#endif
				}
			}
		}
		if (setup["pagerank_build"] == "true" && setup.find("pagerank_file") != setup.end())
		{
			long long steps = 100000000;
			if (setup.find("pagerank_steps") != setup.end())
				steps = LongLong::Parse(setup["pagerank_steps"]);
			double ppb = 0.01;
			if (setup.find("pagerank_ppb") != setup.end())
				ppb = Double::Parse(setup["pagerank_ppb"]);
			IRsystem.countPageRank(setup["pagerank_file"],steps,ppb);
		}
	}
	catch(exception e)
	{
		fprintf(stderr,e.what());
		return 1;
	}


	return 0;
}